package net.wofly.common.pay.web;

import com.alipay.api.AlipayApiException;
import com.egzosn.pay.common.api.PayService;
import com.egzosn.pay.wx.api.WxPayConfigStorage;
import com.egzosn.pay.wx.api.WxPayService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import net.wofly.cashier.order.service.ICashierOrderService;
import net.wofly.cashier.order.util.PayType;
import net.wofly.common.pay.wxpay.config.WxPayConfig;
import net.wofly.common.util.Identities;
import net.wofly.common.web.BaseController;
import net.wofly.framework.util.ResultCode;
import net.wofly.framework.util.ReturnBean;
import net.wofly.sale.order.domain.Order;
import net.wofly.sale.order.domain.PayInfo;
import net.wofly.sale.order.flow.IOrderFlowService;
import net.wofly.sale.order.service.IPayInfoPicService;
import net.wofly.sale.order.service.IPayInfoService;
import net.wofly.sale.order.service.ISaleOrderService;
import net.wofly.sale.order.util.OrderUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Map;


@Controller
@RequestMapping(value = "/api/pay")
@Api(description = "支付")
public class PayController extends BaseController {
    
    Logger logger = LoggerFactory.getLogger(PayController.class);
    
    @Autowired
    ICashierOrderService iCashierOrderService;
    
    @Autowired
    ISaleOrderService iSaleOrderService;
    
    @Autowired
    IPayInfoService iPayInfoService;
    
    @Autowired
    IPayInfoPicService iPayInfoPicService;
    
    @Autowired
    IOrderFlowService iOrderFlowService;
    
    @Autowired
    WxPayConfig wxPayConfig;
    private PayService wxPayService = null;
    
    @PostConstruct
    public void init() {
        WxPayConfigStorage wxPayConfigStorage = new WxPayConfigStorage();
        wxPayConfigStorage.setMchId(wxPayConfig.getMchID());
        wxPayConfigStorage.setAppid(wxPayConfig.getAppID());
        wxPayConfigStorage.setKeyPublic(wxPayConfig.getKey_public());
        wxPayConfigStorage.setSecretKey(wxPayConfig.getKey_private());
        wxPayConfigStorage.setNotifyUrl(wxPayConfig.getNotify_url_pc());
        wxPayConfigStorage.setReturnUrl(wxPayConfig.getReturn_url_pc());
        wxPayConfigStorage.setSignType(wxPayConfig.getSign_type());
        wxPayConfigStorage.setInputCharset("utf-8");
        //https证书设置，退款必须 方式一
        
        wxPayService = new WxPayService(wxPayConfigStorage);
        
        
    }
    
    @RequestMapping(value = "/pay", method = {RequestMethod.POST})
    @ResponseBody
    @ApiOperation(value = "支付")
    @ApiImplicitParams({@ApiImplicitParam(name = "orderID", value = "订单ID", required = true, dataType = "string",
            paramType = "form"), @ApiImplicitParam(name = "orderSource", value = "订单来源: 1: 久隆商贸； 2： 酒店点餐",
            allowableValues = "1,2", required = true, dataType = "string", paramType = "form"), @ApiImplicitParam
            (name = "payType", value = "支付类型（1：现金支付； 2：支付宝支付； 3：微信支付；4：货到付款；5：白条支付；6：签单；9：支付定金；）",
                    allowableValues = "1,2,3,4,5,6,9", required = true, dataType = "int", paramType = "form"),
            @ApiImplicitParam(name = "clientType", value = "客户端类型：1：PC端; 2：移动端_H5；3:移动端_APP", allowableValues = "1,2," +
                    "3", required =
                    true, dataType = "int", paramType = "form"),
            @ApiImplicitParam(name = "price", value = "付款金额", paramType = "form"),
            @ApiImplicitParam(name = "payInfoPicUrls", value = "支付凭证url（多个URL用英文格式竖线|分割）", paramType = "form")})
    public ReturnBean<String> pay(
            String orderID, Integer orderSource, Integer payType,
            Integer clientType, BigDecimal price, String payInfoPicUrls) throws IOException, AlipayApiException {
        logger.info(">>> 支付开始");
        ReturnBean<String> returnBean = null;
        
        if (StringUtils.isEmpty(orderID)) {
            returnBean = new ReturnBean<>(ResultCode.ERROR_DATA, "订单ID不能为空或者来源不正确");
        }
        if (orderSource == null || (orderSource.intValue() != 1 && orderSource != 2)) {
            returnBean = new ReturnBean<>(ResultCode.ERROR_DATA, "订单来源不能为空或者来源不正确");
        }
        if (null == payType || !PayType.isValueCorrect(payType)) {
            returnBean = new ReturnBean<>(ResultCode.ERROR_DATA, "支付类型不正确");
        }
        if (null == clientType || !PayType.isValueCorrect(clientType)) {
            returnBean = new ReturnBean<>(ResultCode.ERROR_DATA, "客户端类型不正确");
        }
        
        //保存支付凭证图片
        if (!StringUtils.isEmpty(payInfoPicUrls)) {
            iPayInfoPicService.savePayInfoPics(orderID, payInfoPicUrls);
        }
        
        if (orderSource.intValue() == 1) {
            //商贸订单
            returnBean = iSaleOrderService.pay(orderID, payType, clientType, price);
        } else if (orderSource.intValue() == 2) {
            // 酒店订单
            returnBean = iCashierOrderService.pay(orderID, payType, clientType);
        }
        logger.info(">>> 支付返回前端数据...进入支付页面，进行支付; ...");
        return returnBean;
    }
    
    @RequestMapping(value = "/notify4AliPay", method = {RequestMethod.POST})
    @ResponseBody
    public String notify4AliPay(HttpServletRequest request) {
        logger.info(">>> notify4AliPay 支付宝支付成功， 执行回调函数");
        logger.info("-----------------------------------------------------------------");
        logger.info(request.getParameterMap().toString());
        logger.info("-----------------------------------------------------------------");
        //执行处理逻辑
        String orderID = request.getParameter("out_trade_no");
        logger.info(">>> 支付宝 异步回调 out_trade_no=" + orderID);
        
        Map<String, String[]> parameterMap = request.getParameterMap();
        
        for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
            logger.info(">>> 支部宝返回的所有参数为" + entry.getKey() + "=" + entry.getValue()[0].toString());
        }
        
        Order order = iSaleOrderService.findOne(orderID);
        
        PayInfo payInfo = new PayInfo();
        payInfo.setPayInfoID(Identities.uuid2());
        payInfo.setOrderID(orderID);
        payInfo.setAmount(
                new BigDecimal(request.getParameter("total_amount")).multiply(new BigDecimal("100")).doubleValue());
        payInfo.setPayAccount(!StringUtils.isEmpty(request.getParameter("buyer_logon_id")) ? request.getParameter(
                "buyer_logon_id") : request.getParameter("buyer_id"));
        payInfo.setPayTime(System.currentTimeMillis());
        payInfo.setPayType(PayType.支付宝.getValue());
        iPayInfoService.save(payInfo);
        
        order.setPayTime(System.currentTimeMillis());
        iSaleOrderService.save(order);
        
        //启动工作流， 根据不同的订单类型
        Integer targetStatus = OrderUtil.getOnlinePayCurrStatus4Workflow(order, true);
        if (targetStatus != null) {
            ReturnBean<String> flowResult = iOrderFlowService.startWorkflow(order.getBuyer(), orderID,
                    targetStatus.toString(), null);
        }
        
        return "success";
    }
    
    @RequestMapping(value = "/notify4WxPay", method = {RequestMethod.POST})
    @ResponseBody
    public String notify4WxPay(HttpServletRequest request) throws IOException {
        logger.info(">>> notify4WxPay 微信支付成功， 执行回调函数");
        logger.info("-----------------------------------------------------------------");
        logger.info(request.getParameterMap().toString());
        logger.info("-----------------------------------------------------------------");
        
        //获取支付方返回的对应参数
        Map<String, Object> params = wxPayService.getParameter2Map(request.getParameterMap(), request.getInputStream());
        if (null == params) {
            return wxPayService.getPayOutMessage("fail", "失败").toMessage();
        }
        for (Map.Entry<String, Object> entry : params.entrySet()) {
            logger.info(">>> 微信返回的所有参数为" + entry.getKey() + "="
                    + (entry.getValue() != null ? entry.getValue().toString() : entry.getValue()));
        }
        
        //校验
        if (wxPayService.verify(params)) {
            //这里处理业务逻辑
            //执行处理逻辑
            String orderID = params.get("out_trade_no").toString();
            logger.info(">>> 微信 异步回调 out_trade_no=" + orderID);
            Order order = iSaleOrderService.findOne(orderID);
            
            PayInfo payInfo = new PayInfo();
            payInfo.setPayInfoID(Identities.uuid2());
            payInfo.setOrderID(orderID);
            payInfo.setAmount(
                    new BigDecimal(params.get("total_fee").toString()).divide(new BigDecimal("100")).doubleValue());
            payInfo.setPayAccount(params.get("openid").toString());
            payInfo.setPayTime(System.currentTimeMillis());
            payInfo.setPayType(PayType.微信支付.getValue());
            iPayInfoService.save(payInfo);
            
            order.setPayTime(System.currentTimeMillis());
            iSaleOrderService.save(order);
            
            //启动工作流， 根据不同的订单类型
            Integer targetStatus = OrderUtil.getOnlinePayCurrStatus4Workflow(order, true);
            if (targetStatus != null) {
                ReturnBean<String> flowResult = iOrderFlowService.startWorkflow(order.getBuyer(), orderID,
                        targetStatus.toString(), null);
            }
            return wxPayService.getPayOutMessage("success", "成功").toMessage();
        }
        return wxPayService.getPayOutMessage("fail", "失败").toMessage();
    }
    
    
    @RequestMapping(value = "/orderPay", method = {RequestMethod.GET})
    public ModelAndView orderPay() {
        logger.info(">>> 进入支付宝支付页面，进行支付");
        return new ModelAndView("pay");
    }
    
    @RequestMapping(value = "/success", method = {RequestMethod.GET})
    public ModelAndView paySuccess() {
        logger.info(">>> 支付 成功");
        return new ModelAndView("paySuccess");
    }
    
}
